package pro.jiug.files.util;

import org.junit.Test;

import java.lang.management.ManagementFactory;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.time.temporal.Temporal;
import java.util.*;

/**
 * Describe : data tools
 * Author : Keffett
 * */
public class DateUtil {

    public static void main(String[] args) throws ParseException {

        Date date2=parseDate("2020-02-28");
        Date date1=parseDate("2021-03-15");

        //System.out.println(dateDiffMonth(date1,date2));
        System.out.println(getDay(date1));//
        System.out.println(getWeek(date1));//
        System.out.println(formatDateYMDW(date1));//

    }

    private static String[][] parsePatterns = {
            {"yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM"},
            {"yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM"},
            {"yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"},
            {"yyyy年MM月dd日", "yyyy年MM月dd日 HH时mm分ss秒", "yyyy年MM月dd日 HH时mm分", "yyyy年MM月"}
    };
    public static String YYYYMMDD = "yyyyMMdd";
    public static String YYYY_MM_DD = parsePatterns[0][0]; // yyyy-MM-dd
    public static String YYYY_MM_DD_HH_MM_SS = parsePatterns[0][1]; // yyyy-MM-dd HH:mm:ss

    // TODO 获取Date时间 S
    /**
     * 将 yyyy-MM-dd 格式字符串转 Date对象
     */
    public static Date parseDate(String stringDate){
        try {
            return new SimpleDateFormat(YYYY_MM_DD).parse(stringDate);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 将 yyyy-MM-dd 格式字符串转 Date对象
     */
    public static Date parseTime(String stringTime){
        try {
            return new SimpleDateFormat(YYYY_MM_DD_HH_MM_SS).parse(stringTime);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 将 stringDate 根据 format 格式字符串转 Date对象
     */
    public static Date parseDate(String stringDate,String format){
        try {
            return new SimpleDateFormat(format).parse(stringDate);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }

    //  获取Date时间 E

    // TODO 获取/传化 String格式时间 S
    /**
     * 获取当前日期 格式为 yyyy-MM-dd
     */
    public static String getDate() {
        return formatDateToStr(new Date(),YYYY_MM_DD);
    }
    /**
     * 获取当前时间 格式为 yyyy-MM-dd HH:mm:ss
     */
    public static String getTime() {
        return formatDateToStr(new Date(),YYYY_MM_DD_HH_MM_SS);
    }

    /**
     * 将Date对象 转为 yyyy-MM-dd 字符串
     */
    public static String formatDateToDStr(Date date) {
        return formatDateToStr(date,YYYY_MM_DD);
    }
    /**
     * 将Date对象 转为 yyyy-MM-dd HH:mm:ss 字符串
     */
    public static String formatDateToTStr(Date date) {
        return formatDateToStr(date,YYYY_MM_DD_HH_MM_SS);
    }
    /**
     * 将Date对象 根据format进行格式化
     */
    public static String formatDateToStr(Date date,String format) {
        return new SimpleDateFormat(format).format(date);
    }
    /**
     * 将Date对象 格式成 年-月-日 星期几
     */
    public static String formatDateYMDW(Date date) {
        String now =new SimpleDateFormat(parsePatterns[3][0]).format(date);
        String[] weekDays = {"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};
        Calendar calendar = getCalendar(date);
        int w = calendar.get(Calendar.DAY_OF_WEEK) - 1;
        return now+" "+weekDays[w];
    }

    // 获取/传化 String格式时间 E

    // TODO 获取时间信息 S
    /**
     * 获取 年
     */
    public static int getYear(Date date) {
        return getCalendar(date).get(Calendar.YEAR);
    }
    /**
     * 获取 月
     */
    public static int getMonth(Date date) {
        return getCalendar(date).get(Calendar.MONTH)+1;
    }
    /**
     * 获取 周几 周日-0 周一 1 。。。周六 6
     */
    public static int getWeek(Date date) {
        return getCalendar(date).get(Calendar.DAY_OF_WEEK)-1;
    }
    /**
     * 获取 几号
     */
    public static int getDay(Date date) {
        return getCalendar(date).get(Calendar.DAY_OF_MONTH);
    }

    // 获取时间信息 E

    // TODO 时间计算 S
    /**
     * 加上指定的年份
     */
    public static Date addYear(Date date, int n) {
        Calendar calendar = getCalendar(date);
        calendar.add(Calendar.YEAR, n);// 增加n年
        Date time = calendar.getTime();
        return time;
    }
    /**
     * 加上指定的月份
     */
    public static Date addMonth(Date date, int n) {
        Calendar calendar = getCalendar(date);
        calendar.add(Calendar.MONTH, n);
        Date time = calendar.getTime();
        return time;
    }
    /**
     * 加上指定的天数
     */
    public static Date addDay(Date date, int n) {
        Calendar calendar = getCalendar(date);
        calendar.add(Calendar.DAY_OF_MONTH, n);
        Date time = calendar.getTime();
        return time;
    }
    /**
     * 加上指定的小时
     */
    public static Date addHour(Date date, int n) {
        Calendar cal = getCalendar(date);// 当前系统时间转Calendar类型
        cal.add(Calendar.HOUR, n);// 增加n个小时
        Date time = cal.getTime();
        return time;
    }
    /**
     * 加上指定的分钟
     */
    public static Date addMinute(Date date, int n) {
        Calendar cal = getCalendar(date);// 当前系统时间转Calendar类型
        cal.add(Calendar.MINUTE, n);// 增加多少分
        Date time = cal.getTime();
        return time;
    }
    /**
     * 加上指定的 秒
     */
    public static Date addSecond(Date date, int n) {
        Calendar cal = getCalendar(date);// 当前系统时间转Calendar类型
        cal.add(Calendar.SECOND, n);// 增加多少秒
        Date time = cal.getTime();
        return time;
    }

    /**
     * 计算两个时间差 微秒
     */
    public static long dateDiff(Date date1, Date date2) {
        return date1.getTime()-date2.getTime();
    }
    /**
     * 计算两个时间差 秒
     */
    public static long dateDiffs(Date date1, Date date2) {
        return dateDiff(date1, date2)/1000;
    }
    /**
     * 计算两个时间差 分
     */
    public static long dateDiffm(Date date1, Date date2) {
        return dateDiff(date1, date2)/1000/60;
    }
    /**
     * 计算两个时间差 时
     */
    public static long dateDiffh(Date date1, Date date2) {
        return dateDiff(date1, date2)/1000/60/60;
    }
    /**
     * 计算两个时间差 天
     */
    public static int dateDiffd(Date date1, Date date2) {
        return (int)dateDiff(date1, date2)/1000/60/60/24;
    }
    /**
     * 计算两个时间差 周
     */
    public static int dateDiffw(Date date1, Date date2) {
        return dateDiffd(date1, date2)/7;
    }
    /**
     * 计算两个时间差 月
     */
    public static int dateDiffM(Date date1, Date date2) {
        return dateDiffd(date1, date2)/30;
    }
    /**
     * 计算两个时间差 年
     */
    public static int dateDiffy(Date date1, Date date2) {
        return dateDiffd(date1, date2)/365;
    }

    /**
     * 计算两个时间差 天 按天差
     */
    public static int dateDiffDay(Date date1, Date date2) {
        return dateDiffd(clearTime(date1),clearTime(date2));
    }
    /**
     * 计算两个时间差 周 按周差
     */
    public static int dateDiffWeek(Date date1, Date date2) {
        Calendar calendar1 = getCalendar(clearTime(date1));
        Calendar calendar2 = getCalendar(clearTime(date2));

        calendar1.set(Calendar.DAY_OF_WEEK,Calendar.MONDAY);
        calendar2.set(Calendar.DAY_OF_WEEK,Calendar.MONDAY);

        return dateDiffd(calendar1.getTime(),calendar2.getTime())/Calendar.DAY_OF_WEEK;
    }
    /**
     * 计算两个时间差 月 按月差
     */
    public static int dateDiffMonth(Date date1, Date date2) {
        Calendar calendar1 = getCalendar(date1);
        Calendar calendar2 = getCalendar(date2);

        int year1=calendar1.get(Calendar.YEAR);
        int year2=calendar2.get(Calendar.YEAR);
        int month1=calendar1.get(Calendar.MONTH);
        int month2=calendar2.get(Calendar.MONTH);

        return (year1-year2)*12+month1-month2;
    }
    /**
     * 计算两个时间差 年 按年差
     */
    public static int dateDiffYear(Date date1, Date date2) {
        Calendar calendar1 = getCalendar(date1);
        Calendar calendar2 = getCalendar(date2);

        int year1=calendar1.get(Calendar.YEAR);
        int year2=calendar2.get(Calendar.YEAR);

        return year1-year2;
    }

    /**
     * 计算两个时间差 **天**小时**分钟
     */
    public static String dateDiffString(Date endDate, Date nowDate) {
        long nd = 1000 * 24 * 60 * 60;
        long nh = 1000 * 60 * 60;
        long nm = 1000 * 60;
        // 获得两个时间的毫秒时间差异
        long diff = endDate.getTime() - nowDate.getTime();
        // 计算差多少天
        long day = diff / nd;
        // 计算差多少小时
        long hour = diff % nd / nh;
        // 计算差多少分钟
        long min = diff % nd % nh / nm;

        return day + "天" + hour + "小时" + min + "分钟";
    }
    public static String getRemainderTime(Date currentTime, Date firstTime) {
        long diff = currentTime.getTime() - firstTime.getTime();

        Calendar currentTimes = getCalendar(currentTime);// 当前系统时间转Calendar类型
        Calendar firstTimes = getCalendar(firstTime);// 查询的数据时间转Calendar类型
        int year = currentTimes.get(Calendar.YEAR) - firstTimes.get(Calendar.YEAR);// 获取年
        int month = currentTimes.get(Calendar.MONTH) - firstTimes.get(Calendar.MONTH);
        int day = currentTimes.get(Calendar.DAY_OF_MONTH) - firstTimes.get(Calendar.DAY_OF_MONTH);
        if (day < 0) {
            month -= 1;
            currentTimes.add(Calendar.MONTH, -1);
            day = day + currentTimes.getActualMaximum(Calendar.DAY_OF_MONTH);// 获取日
        }
        if (month < 0) {
            month = (month + 12) % 12;// 获取月
            year--;
        }
        long days = diff / (1000 * 60 * 60 * 24);
        long hours = (diff - days * (1000 * 60 * 60 * 24)) / (1000 * 60 * 60); // 获取时
        long minutes = (diff - days * (1000 * 60 * 60 * 24) - hours * (1000 * 60 * 60)) / (1000 * 60);// 获取分钟
        long s = (diff / 1000 - days * 24 * 60 * 60 - hours * 60 * 60 - minutes * 60);// 获取秒
        if (days > 0) {
            return days + "天";
        } else {
            return hours + "小时" + minutes + "分" + s + "秒";
        }

    }
    public static String getRemainderDate(Date currentTime, Date firstTime) {

        long diff = currentTime.getTime() - firstTime.getTime();

        Calendar currentTimes = getCalendar(currentTime);// 当前系统时间转Calendar类型
        Calendar firstTimes = getCalendar(firstTime);// 查询的数据时间转Calendar类型
        int year = currentTimes.get(Calendar.YEAR) - firstTimes.get(Calendar.YEAR);// 获取年
        int month = currentTimes.get(Calendar.MONTH) - firstTimes.get(Calendar.MONTH);
        int day = currentTimes.get(Calendar.DAY_OF_MONTH) - firstTimes.get(Calendar.DAY_OF_MONTH);
        if (day < 0) {
            month -= 1;
            currentTimes.add(Calendar.MONTH, -1);
            day = day + currentTimes.getActualMaximum(Calendar.DAY_OF_MONTH);// 获取日
        }
        if (month < 0) {
            month = (month + 12) % 12;// 获取月
            year--;
        }
        long days = diff / (1000 * 60 * 60 * 24);
        long hours = (diff - days * (1000 * 60 * 60 * 24)) / (1000 * 60 * 60); // 获取时
        long minutes = (diff - days * (1000 * 60 * 60 * 24) - hours * (1000 * 60 * 60)) / (1000 * 60);// 获取分钟
        long s = (diff / 1000 - days * 24 * 60 * 60 - hours * 60 * 60 - minutes * 60);// 获取秒
        String CountTime = year + "年" + month + "月" + day + "天" + hours + "小时" + minutes + "分" + s + "秒";
        return CountTime;
    }
    public static String switchString(Date payDate) {
        Calendar cal = getCalendar(payDate);// 当前系统时间转Calendar类型
        Date time = cal.getTime();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(time);
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH) + 1;
        int day = calendar.get(Calendar.DAY_OF_MONTH);
        return year + "年" + month + "月" + day + "日";
    }
    // 时间计算 E

    // TODO 时间比较 S
    /**
     * 比较两个日期的年月日是否相同 - 是否为同一天
     */
    public static boolean sameDate(Date date1, Date date2) {
        SimpleDateFormat fmt = new SimpleDateFormat(YYYYMMDD);
        return fmt.format(date1).equals(fmt.format(date2));
    }
    /**
     * 比较两个时间大小 date1 > date2 = true
     */
    public static boolean compare(Date date1,Date date2){
        if(date1.getTime()>date2.getTime()){
            return true;
        }
        return false;
    }
    /**
     * 比较两个时间大小 String 相同格式 date1 > date2 = true
     */
    public static boolean compare(String date1,String date2){
        if(date1.compareTo(date2)>=0){
            return true;
        }
        return false;
    }

    // 时间比较 E

    /**
     * 获取服务器启动时间
     */
    public static Date getServerStartDate() {
        long time = ManagementFactory.getRuntimeMXBean().getStartTime();
        return new Date(time);
    }

    /**
     * 获取 Calendar 对象
     */
    private static Calendar getCalendar(){
        return getCalendar(new Date());
    }
    private static Calendar getCalendar(Date date){
        Calendar calendar=Calendar.getInstance(Locale.CHINA);   //时区 中国
        calendar.setFirstDayOfWeek(Calendar.MONDAY);            //一周开始日 周一
        calendar.setTimeInMillis(date.getTime());
        return calendar;
    }

    /**
     * 清除时分秒
     */
    public static Date clearTime(Date date){
        return parseDate(formatDateToDStr(date));
    }

    /**
     * 打印一周的日期
     */
    @Test
    public void printWeekDate(){
        SimpleDateFormat sdf=new SimpleDateFormat(YYYY_MM_DD);

        Calendar calendar=Calendar.getInstance(Locale.CHINA);
        calendar.setFirstDayOfWeek(Calendar.MONDAY);
        calendar.setTimeInMillis(System.currentTimeMillis());

        for (int i = 1; i <= 7; i++) {
            calendar.set(Calendar.DAY_OF_WEEK,i);
            System.out.println(formatDateToDStr(calendar.getTime()));
        }

        //这周日几号
        calendar.set(Calendar.DAY_OF_WEEK,Calendar.SUNDAY);
        System.out.println("这周日:"+formatDateToDStr(calendar.getTime()));

        //这周一几号
        calendar.set(Calendar.DAY_OF_WEEK,Calendar.MONDAY);
        System.out.println("这周一:"+formatDateToDStr(calendar.getTime()));

        //下周一几号
        calendar.add(Calendar.DATE,7);
        System.out.println("下周一:"+formatDateToDStr(calendar.getTime()));

    }

}